package com.xiyu.service.job;

import com.xiyu.service.framework.job.core.handler.JobHandler;
import com.xiyu.service.enums.elder.register.ElderCheckInStatusEnum;
import com.xiyu.service.enums.fee.charge.FeeChargeTypeEnum;
import com.xiyu.service.enums.plan.NursePlanExecTypeEnum;
import com.xiyu.service.model.elder.register.ElderCheckIn;
import com.xiyu.service.model.fee.recharge.FeeRecharge;
import com.xiyu.service.model.fee.recharge.FeeRechargeDraft;
import com.xiyu.service.model.fee.recharge.FeeRechargeFlow;
import com.xiyu.service.model.fee.recharge.FeeRechargeFlowDraft;
import com.xiyu.service.model.nurse.plan.NursePlan;
import com.xiyu.service.model.nurse.plan.NursePlanDetail;
import com.xiyu.service.model.nurse.plan.NursePlanDetailDraft;
import com.xiyu.service.model.system.user.SystemUser;
import com.xiyu.service.repository.elder.register.ElderCheckInRepository;
import com.xiyu.service.repository.fee.recharge.FeeRechargeFlowRepository;
import com.xiyu.service.repository.fee.recharge.FeeRechargeRepository;
import com.xiyu.service.repository.nurse.plan.NursePlanDetailRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Component
public class retirementFeeJob implements JobHandler {

    @Resource
    ElderCheckInRepository elderCheckInRepository;

    @Resource
    FeeRechargeRepository feeRechargeRepository;

    @Resource
    FeeRechargeFlowRepository feeRechargeFlowRepository;

    @Resource
    NursePlanDetailRepository nursePlanDetailRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String execute(String param) throws Exception {
        List<ElderCheckIn> elderCheckIns = elderCheckInRepository.findDetailByStatus(ElderCheckInStatusEnum.CHECKED_IN.getValue());
        int currentDay = LocalDate.now().getDayOfMonth();
        DayOfWeek currentWeek = LocalDate.now().getDayOfWeek();
        for(ElderCheckIn elderCheckIn: elderCheckIns){
            Optional<FeeRecharge>  optionalFeeRecharge =  feeRechargeRepository.findByElderId(elderCheckIn.elderId());
            if(!optionalFeeRecharge.isPresent()){
                return "老人ID" + elderCheckIn.elderId() + "不存在预充值费用" ;
            }
            BigDecimal totalRecharge = optionalFeeRecharge.get().totalRecharge();
            if(elderCheckIn.bedInfo() != null){
                if(Objects.equals(Objects.requireNonNull(elderCheckIn.bedInfo()).chargeType(), FeeChargeTypeEnum.DAY.getValue())
                || currentDay == 1){

                    insertRechargeFlow(totalRecharge, 1L, Objects.requireNonNull(elderCheckIn.bedInfo()).price(), elderCheckIn.elderId());
                    totalRecharge = totalRecharge.subtract(Objects.requireNonNull(elderCheckIn.bedInfo()).price());
                }
            }

            if(elderCheckIn.nursePlan() != null){
                List<NursePlanDetail> nursePlanDetails = nursePlanDetailRepository.findByPlanId(elderCheckIn.nursePlanId());
                for(NursePlanDetail detail : nursePlanDetails){
                    boolean isExec = false;
                    if(Objects.equals(detail.execType(), NursePlanExecTypeEnum.MOUTH.getValue())){
                        for(Long day : detail.execFrequency()){
                            if(day.intValue() == currentDay){
                                BigDecimal flowFee = Objects.requireNonNull(Objects.requireNonNull(detail.item()).itemFee().multiply(BigDecimal.valueOf(detail.execTime().size())));
                                insertRechargeFlow(totalRecharge, 2L, flowFee, elderCheckIn.elderId());
                                totalRecharge = totalRecharge.subtract(flowFee);
                                isExec = true;
                            }
                        }
                    }else if(Objects.equals(detail.execType(), NursePlanExecTypeEnum.WEEK.getValue())){
                        for(Long week : detail.execFrequency()){
                            if(currentWeek.getValue() == week){
                                BigDecimal flowFee = Objects.requireNonNull(Objects.requireNonNull(detail.item()).itemFee().multiply(BigDecimal.valueOf(detail.execTime().size())));
                                insertRechargeFlow(totalRecharge, 2L, flowFee, elderCheckIn.elderId());
                                totalRecharge = totalRecharge.subtract(flowFee);
                                isExec = true;
                            }
                        }
                    }else if(Objects.equals(detail.execType(), NursePlanExecTypeEnum.DAY.getValue())){
                        BigDecimal flowFee = Objects.requireNonNull(Objects.requireNonNull(detail.item()).itemFee().multiply(BigDecimal.valueOf(detail.execTime().size())));
                        insertRechargeFlow(totalRecharge, 2L, flowFee, elderCheckIn.elderId());
                        totalRecharge = totalRecharge.subtract(flowFee);
                        isExec = true;
                    }else {
                        if(Objects.equals(detail.lastExecTime(), "")){
                            BigDecimal flowFee = Objects.requireNonNull(Objects.requireNonNull(detail.item()).itemFee().multiply(BigDecimal.valueOf(detail.execTime().size())));
                            insertRechargeFlow(totalRecharge, 2L, flowFee, elderCheckIn.elderId());
                            totalRecharge = totalRecharge.subtract(flowFee);
                            isExec = true;
                        }else{
                            LocalDate  lastExecTime = LocalDateTime.parse(detail.lastExecTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toLocalDate();
                            if(!detail.execFrequency().isEmpty() && ChronoUnit.DAYS.between(lastExecTime, LocalDateTime.now().toLocalDate()) > detail.execFrequency().get(0)){
                                BigDecimal flowFee = Objects.requireNonNull(Objects.requireNonNull(detail.item()).itemFee().multiply(BigDecimal.valueOf(detail.execTime().size())));
                                insertRechargeFlow(totalRecharge, 2L, flowFee, elderCheckIn.elderId());
                                totalRecharge = totalRecharge.subtract(flowFee);
                                isExec = true;
                            }
                        }
                    }
                    if(isExec){
                        // 将 LocalDate 转换为 LocalDateTime
                        LocalDateTime currentDateTime = LocalDate.now().atTime(LocalTime.MIDNIGHT); // 或 LocalTime.now() 获取当前时间

                        // 将 LocalDateTime 格式化为字符串
                        String currentDate = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        detail = NursePlanDetailDraft.$.produce(detail, draft -> {
                            draft.setLastExecTime(currentDate);
                        });
                        nursePlanDetailRepository.update(detail);
                    }

                }
            }

            if(elderCheckIn.restaurantCombo() != null){
                if(Objects.equals(Objects.requireNonNull(elderCheckIn.restaurantCombo()).chargeType(), FeeChargeTypeEnum.DAY.getValue())
                ||currentDay == 1){
                    insertRechargeFlow(totalRecharge, 3L, Objects.requireNonNull(elderCheckIn.restaurantCombo()).price(), elderCheckIn.elderId());
                    totalRecharge = totalRecharge.subtract(Objects.requireNonNull(elderCheckIn.bedInfo()).price());
                }
            }

            BigDecimal finalTotalRecharge1 = totalRecharge;
            FeeRecharge feeRecharge = FeeRechargeDraft.$.produce(optionalFeeRecharge.get(), draft -> {
                draft.setTotalRecharge(finalTotalRecharge1);
            });
            feeRechargeRepository.update(feeRecharge);
        }
        return "费用结算定时任务" ;
    }

    private void insertRechargeFlow(BigDecimal totalRecharge, Long FeeCategory,BigDecimal flowFee, Long elderId){
        FeeRechargeFlow bedFlow = FeeRechargeFlowDraft.$.produce(draft -> {
            draft.setBeforeFee(totalRecharge).setFee(flowFee)
                    .setAfterFee(totalRecharge.subtract(flowFee))
                    .setFeeCategoryId(FeeCategory).setElderId(elderId);
        });
        feeRechargeFlowRepository.insert(bedFlow);
    }
}
